#!/usr/bin/env python
#-*- coding: utf-8 -*-

# @autor: Elísio Gonçalves Gomes Ribeiro
# @curso: Engenharia Informática 3ºano nº4708
# @subject: Estrutura de Dados e Algoritmo
# @@version: 1.0.0 2012/2013
# @google-code:

###############################################################################
#
#
#

#------------------------------------------------------------------------------


import random
#from algOrd import Algord
import time
import stats as stc
from OPFile import OPFile


class DataGen:
    """
    classe q gera listas d dados com os tamanhos indicados
    ou le dos ficheiro indicados o conteudo a operar sobre
    """
    def __init__(self):
        """
        Algoritmo
        Repeticaoo
        Tamanho dos dados(kbps)
        Tempos(secs)
        Ficheiro(caminho absoluto)
        """
        self.OF = OPFile()
        self.iList = None
        self.lsize = 0
        self.min_v = 0
        self.max_v = 0
        self.rep_test = 0
        self.cur_graph = None
        self.el_Times = {'IS':{},'BS':{},'HS':{},'QS':{},'MS':{}}

    
    def __words_fill(self, size):
        """
        recebe um paramentro size para o tasmanho da lista a devolver
        cria uma lista d strings com esse tamanho e devolve
        """
        alphab = "abcdefghijlmnopqrstuvwxz"
        for k in xrange(size):
            word = random.randint(3, 8)
            
            if (word == 4 or word == 3):
                frst = random.randint(0,21)
                self.iList.append(alphab[frst:frst + 4])
                
            if (word == 5):
                frst = random.randint(0,19)
                self.iList.append(alphab[frst:frst + 5])
                
            if (word == 6):
                frst = random.randint(0,18)
                self.iList.append(alphab[frst:frst + 6])
            if (word == 7):
                frst = random.randint(0,17)
                self.iList.append(alphab[frst:frst + 7])
            if (word == 8):
                frst = random.randint(0,16)
                self.iList.append(alphab[frst:frst + 8])
            pass
        pass
    
    
    def __numbers_fill(self, lst_size, low_lim, uper_lim):
        """
        devolve uma lista d numeros aleatorios entre o low_lim e uper_lim
        com o tamanho lst_size
        """
        for k in range(lst_size):
            numbr = random.randint(low_lim, uper_lim)
            self.iList.append(numbr)
        pass
        
    #
    def gen_strings(self):
        """
        generates list of size l_size of random string 
        based on ordered letters of the alphabet
        """
        self.iList = []
        self.__words_fill(self.lsize)
        pass

    def gen_numbers(self):
        """
        generates list of size l_size of random number 
        between the min_val and max_val given params
        """
        self.iList = []
        self.__numbers_fill(self.lsize, self.min_v, self.max_v)
        pass

    def load_from_file(self, fname):
        """
        verifiy if the given file is suported and
        load data from given file and 
        return a list to work on
        """
        try:
            self.OF.read_file_in(fname)
        except: raise
        else:
            return self.OF.head_file
        pass

    def get_read_content(self):
        return self.OF.data

    def save_el_times(self):
        
        for algo, mtime in self.el_Times.items():
            if (len(mtime) > 0):
                st = []
                st.append('# Measured time')
                fname = algo + '_mtime.txt'
                de = 1
                for size, res in mtime.items():
                    st.append('\n'+algo+'_'+str(size)+ ':')
                    [st.append(k) for k in res[0]]
                pass
                try:
                    if(de == 1): self.OF.save_file(fname, st)
                except: raise
            pass
        pass

    def save_stats(self):
        fname = 'algo_avg_dev.txt'
        st = []
        de = 0
        st.append('# Average and Deviation of Meseared Times')
        st.append("#{0:>15} {1:>15} {2:>15}".format('Size', 'Mean', 'Deviation\n'))
        for algo, mtime in self.el_Times.items():
            if (len(mtime) > 0):
                de = 1
                st.append(algo)
                for size, res in mtime.items():                    
                    st.append("{0:>15} : {1:>15} {2:>15}".format(size, res[1], res[2]))
                pass
            pass
        pass
        try:
            if(de == 1): self.OF.save_file(fname, st)
        except: raise

    def run_test(self, algo, f):
        res_time = []
        for k in range(self.rep_test):
            
            t_init = time.time()
            f()
            t_fin = time.time()
            
            res = t_fin - t_init
            res_time.append(round(res, 6))
        pass
        dev,avr = stc.calc_avg_dev(res_time)
        d = self.el_Times[algo]
        d[self.lsize] = tuple([res_time, avr, dev])

    def draw_graph(self):
        xlst = []
        ylst4 = []
        ylst5 = []
        dlst = self.el_Times.values()
        [xlst.append(k) for dv in dlst for k in dv.keys() if k not in xlst]
        labellst = self.el_Times.keys()
        xlst.sort()
        for k in xlst:
            ylst4 = []
            for v in self.el_Times.values():
                ylst4.append(v[k][1])
            ylst5.append(ylst4)			
        pass
        
        return  stc.draw44(xlst,ylst5,labellst)

    def draw_graph_algo(self, algo, dData):
        lsts = dData.keys()
        el_time = [max(dData[k][0]) for k in lsts]
        mVal = [dData[k][1] for k in lsts]
        dVal =[dData[k][2] for k in lsts]
        
        grph = stc.draw_g_algo(algo, lsts, el_time, mVal, dVal)
        return grph

